一、光源
环境光(Ambient):
最简单的光源,没有光源位置。无论对象在何处,其上的每个像素都有相同的光照。
float globalAmbient[4] = {0.6f, 0.,6f, 0.6f, 1.0f};
定向光(Directional light):
定向光也没有光源位置,但是具有方向。
定向光用于模拟光源位置很远以至于光线接近平行的情况。(例如太阳)
点光源(point light):
又称位置光,在场景中有特定位置。但对于场景中每个点的光照方向都不同。
点光源有衰减因子,衰减因子有很多建模方式。最常用建模方式:factor = 1 / (k1 + k2*d + k3*d*d)
。
※聚光灯(spot light):
限制了方向范围的点光源。
二、光照模型
光照模型(Lighting model)也称为着色模型(Shading model),有时也称为反射模型(Reflection model)。
最常见的光照模型是标准光照模型。(一种ADS光照模型)
其他的复杂光照模型有基于物理的渲染(PBR)的BRDF光照模型等。
三、标准光照模型(Blinn-Phong模型)
三部分:
-
Ambient环境光:
全局变量。 -
Diffuse漫反射:
lambert模型。 -
Specular高光反射:
Phong模型和Blinn模型。
公式:
$I_{observed} = I_{ambient} + I_{diffuse} + I_{specular}$
- $I_{diffuse} = c_{light}·m_{diffuse}·max(0, n·l)$
- $I_{specular} = c_{light}·m_{specular}·max(0, n·l)^{m_{gloss}}$
逐像素和逐顶点光照:
-
逐顶点光照:高洛德(Gouraud)着色。
-
逐像素光照:Phong着色。
Blinn-Phong着色:
Blinn在Phong着色上引入了角平分向量H,取代了反射向量R的计算。(Phong着色中反射向量R的计算消耗很大)
角平分向量H的计算在片段着色器或者顶点着色器中进行都可以。
Blinn-Phong着色器代码:
//顶点着色器代码:
#version 430
struct DirectionalLight
{
vec4 color;
vec3 dir;
};
struct Material
{
vec4 diffuse;
vec4 specular;
float gloss;
};
layout (location = 0) in vec3 position;
layout (location = 1) in vec2 texcoords;
layout (location = 2) in vec3 normal;
uniform mat4 m_matrix;
uniform mat4 v_matrix;
uniform mat4 mv_matrix;
uniform mat4 proj_matrix;
uniform mat4 norm_matrix;
uniform vec4 ambient;
uniform DirectionalLight light;
uniform Material material;
//layout(binding = 0) uniform sampler2D samp;
out vec3 varyingPos;
out vec3 varyingNormal;
out vec2 uv;
void main(void)
{
varyingPos = (mv_matrix * vec4(position, 1.0)).xyz;
varyingNormal = (norm_matrix * vec4(normal, 1.0)).xyz;
uv = texcoords;
gl_Position = proj_matrix * mv_matrix * vec4(position, 1.0);
}
//片段着色器代码:
#version 430
struct DirectionalLight
{
vec4 color;
vec3 dir;
};
struct Material
{
vec4 diffuse;
vec4 specular;
float gloss;
};
in vec3 varyingPos;
in vec3 varyingNormal;
in vec2 uv;
out vec4 color;
uniform mat4 m_matrix;
uniform mat4 v_matrix;
uniform mat4 mv_matrix;
uniform mat4 proj_matrix;
uniform mat4 norm_matrix;
uniform vec4 ambient;
uniform DirectionalLight light;
uniform Material material;
layout(binding = 0) uniform sampler2D samp;
void main(void)
{
vec3 N = normalize(varyingNormal);
vec3 L = normalize((v_matrix * vec4(-light.dir, 0.0)).xyz);
vec3 V = normalize(-varyingPos);
vec3 H = normalize(L + V);
vec3 diffuse = light.color.xyz * material.diffuse.xyz * max(0.0, dot(N, L));
vec3 specular = light.color.xyz * material.specular.xyz * pow(max(0.0, dot(H, N)), material.gloss);
color = texture(samp, uv) * vec4((ambient.xyz + diffuse + specular), 1.0);
}